using System;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using SQLExecutorControls;
using SQLExecutor.Common;
using SQLExecutor.DBHelper;
using System.Collections;

namespace SQLExecutor.Business
{

    /// <summary>
    /// 
    /// </summary>
    public class SQLScript
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="msg"></param>
        public delegate void SuccessHandler(int index, string msg);
        /// <summary>
        /// 
        /// </summary>
        public event SuccessHandler OnScriptSuccess;
        /// <summary>
        /// 
        /// </summary>
        public event SuccessHandler OnBlockSuccess;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="index"></param>
        /// <param name="error"></param>
        public delegate void ErrorScriptHandler(int index, List<DBError> error);
        /// <summary>
        /// 
        /// </summary>
        public event ErrorScriptHandler OnScriptError;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="error"></param>
        public delegate void ErrorBlockHandler(DBError error);
        /// <summary>
        /// 
        /// </summary>
        public event ErrorBlockHandler OnBlockError;

        /// <summary>
        /// 
        /// </summary>
        private DBHelper.DBType _type;

        /// <summary>
        /// 
        /// </summary>
        private DataBaseConnectionInfo _connnection;
        /// <summary>
        /// 
        /// </summary>
        private List<DictionaryEntry> _scripts;
        /// <summary>
        /// 
        /// </summary>
        private string _separator;
        /// <summary>
        /// 
        /// </summary>
        private bool _stopIfError;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="engine"></param>
        /// <param name="connection"></param>
        public SQLScript(DataBaseConnectionInfo connection, List<DictionaryEntry> scripts, bool stopIfError)
        {
            OnScriptSuccess += new SuccessHandler(SQLScript_OnMessage);
            OnBlockError += new ErrorBlockHandler(SQLScript_OnError);
            OnBlockSuccess += new SuccessHandler(SQLScript_OnSuccessBlock);
            OnScriptError += new ErrorScriptHandler(SQLScript_OnErrorScript);

            switch (connection.DbEngine)
            {
                case BdEngineType.MSSQL:
                    _type = SQLExecutor.DBHelper.DBType.SQLSERVER;
                    _separator = "^GO";
                    break;
                case BdEngineType.ORACLE:
                    _type = SQLExecutor.DBHelper.DBType.ORACLE;
                    _separator = "[\t\n\x0B\f\r]+/[ \t\n\x0B\f\r]+";
                    break;
            }
            _connnection = connection;
            _scripts = scripts;
            _stopIfError = stopIfError;

        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="index"></param>
        /// <param name="error"></param>
        void SQLScript_OnErrorScript(int index, List<DBError> error)
        {

        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="index"></param>
        /// <param name="msg"></param>
        void SQLScript_OnSuccessBlock(int index, string msg)
        {

        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="script"></param>
        /// <param name="separator"></param>
        /// <param name="replacement"></param>
        /// <param name="patterns"></param>
        /// <returns></returns>
        public void ExecuteScript()
        {
            DBHelper.DBHelper _helper = new DBHelper.DBHelper(_connnection, _type);

            List<DBError> errors = new List<DBError>();

            foreach (DictionaryEntry entry in _scripts)
            {
                //Divide el script en las regiones especificadas por el separador usando una expresion regular
                List<ExecuteRegionInfo> region = Business.TextUtilities.Divide(entry.Value.ToString(), _separator);

                errors.Clear();

                int fileIndex = -1;

                #region Recorre los bloques de cada script detectados
                for (int i = 0; i < region.Count; i++)
                {
                    string block = region[i].Text;

                    fileIndex = (int)entry.Key;

                    #region Ejecuta un bloque del codigo
                    try
                    {
                        if (block.Length > 0)
                        {
                            System.Diagnostics.Trace.WriteLine("");
                            System.Diagnostics.Trace.WriteLine(block);
                            System.Diagnostics.Trace.WriteLine("");

                            //Ejecuta el script
                            _helper.Execute(block);

                            OnBlockSuccess(i, "Bloque ejecutado Correctamente " + i.ToString());
                        }
                    }
                    catch (DBError ex)
                    {
                        errors.Add(ex);
                        OnBlockError(ex);

                        if (_stopIfError && errors.Count > 0)
                        {
                            OnScriptError(fileIndex, errors);
                            return;
                        }
                    }
                    #endregion
                }
                #endregion

                if (errors.Count == 0)
                {
                    //lanza el evento despues de la ejecucion del la sentencia
                    OnScriptSuccess(fileIndex, Messages.SCRIPT_SUCCESS);
                }
                else
                {
                    OnScriptError(fileIndex, errors);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="index"></param>
        /// <param name="msg"></param>
        void SQLScript_OnMessage(int index, string msg)
        {

        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="error"></param>
        void SQLScript_OnError(SQLExecutor.DBHelper.DBError error)
        {

        }
    }

}
